package com.gxa.saas.portal.config;

import com.gxa.saas.portal.oauth2.OAuth2Filter;
import com.gxa.saas.portal.oauth2.OAuth2Realm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * ConditionalOnMissingBean注解是Spring提供, 判断bean是否已经被创建过,如果有就抛出异常
 * @author bill
 * @date 2022/6/29 9:37
 */
@Configuration
public class ShiroConfig {

    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator
    defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
        defaultAAP.setProxyTargetClass(true);
        return defaultAAP;
    }

   /* @Bean
    public AdminRealm adminRealm() {
        AdminRealm adminRealm = new AdminRealm();
        return adminRealm;
    }*/

    @Autowired
    OAuth2Realm adminRealm;

    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new
                DefaultWebSecurityManager();
//        securityManager.setRealm(adminRealm());
        securityManager.setRealm(adminRealm);
        return securityManager;
    }

    //Filter工厂，设置对应的过滤条件和跳转条件
    // shiro 提供了11个过滤器类型(user/authc/jwt/anon....)
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, String> map = new LinkedHashMap<>();

        Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
        //shiro提供了一个自定义过滤器的机制,改变登录不成功时的处理方式: 不用跳转到login.jsp/ /login
        // 希望: 返回给前端json
        filters.put("oAuth2Filter",new OAuth2Filter());

        //对所有请求都需要用户认证
        // /login /admin/login /admin/add ....

        // shiro在过滤器拦截目标接口时,不允许赋空值
      //  map.put("", "authc");  // 错的


        // 匿名访问的接口: anon表示匿名访问的过滤器
        // 一般注册和登录可以匿名访问
        // 注册: 生成用户
        // 登录: 生成可认证和授权的信息

        map.put("/**/register","anon");
        map.put("/**/login","anon");
        map.put("/swagger-ui/**","anon");
        map.put("/address/**","anon");
        map.put("/cart/**","anon");
        map.put("/commodity/**","anon");
        map.put("/seckill/**","anon");
        map.put("/GoodsIndent/**","anon");
        map.put("/Classify/**","anon");
        map.put("/GoodsDetails/**","anon");
        map.put("/GoodsHomepage/**","anon");
        map.put("/doc.html","anon");
        map.put("/swagger-resources/**","anon");
        map.put("/webjars/**","anon");
        map.put("/v3/**","anon");
        map.put("/**", "oAuth2Filter");

        //登录, 当shiro发现用户不具备角色和权限的时候,会自动跳转:  /user/add
        //        // 1.最初的方式: 跳转到 login.jsp 页面
        //        // 2. 通过setLoginUrl 指定备用的访问接口
        //        // 3. 把需要登录的异常信息暴露给前端
        //       // shiroFilterFactoryBean.setLoginUrl("/login");

        //首页
       // shiroFilterFactoryBean.setSuccessUrl("/index");  index.jsp

        //错误页面，认证不通过跳转
       // shiroFilterFactoryBean.setUnauthorizedUrl("/error");  error.jsp
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor
    authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}
